package com.engine.salary.entity.taxdeclaration.bo;

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.constant.TaxDeclarationDataIndexConstant;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.datacollection.AddUpSituation;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationDetailListDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationDetailPO;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.salaryaccounting.EmployeeTypeEnum;
import com.engine.salary.enums.salarysob.IncomeCategoryEnum;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.page.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.engine.salary.util.db.IdGenerator;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.hrm.User;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 个税申报表
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class TaxDeclarationBO {
    private static EncryptUtil encryptUtil = new EncryptUtil();

    public static List<TaxDeclarationListDTO> convert2ListDTO(List<TaxDeclarationPO> taxDeclarations,
                                                              List<DataCollectionEmployee> simpleEmployees,
                                                              List<TaxAgentPO> taxAgents) {
        if (CollectionUtils.isEmpty(simpleEmployees)) {
            simpleEmployees = new ArrayList<>();
        }
        Map<Long, String> taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgentPO::getId,
                TaxAgentPO::getName);
        Map<Long, String> employeeNameMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername);
        return taxDeclarations.stream()
                .map(taxDeclarationPO -> {
                    IncomeCategoryEnum incomeCategoryEnum = IncomeCategoryEnum.parseByValue(taxDeclarationPO.getIncomeCategory());
                    return TaxDeclarationListDTO.builder()
                            .id(taxDeclarationPO.getId())
                            .incomeCategory(Optional.ofNullable(incomeCategoryEnum)
                                    .map(o -> SalaryI18nUtil.getI18nLabel(o.getLabelId(), o.getDefaultLabel()))
                                    .orElse(StringUtils.EMPTY))
                            .salaryMonth(taxDeclarationPO.getSalaryMonth())
                            .taxAgentId(taxDeclarationPO.getTaxAgentId())
                            .taxAgentName(taxAgentNameMap.getOrDefault(taxDeclarationPO.getTaxAgentId(), ""))
                            .taxCycle(taxDeclarationPO.getTaxCycle())
                            .operateEmployeeId(taxDeclarationPO.getCreator())
                            .operateEmployeeName(employeeNameMap.getOrDefault(taxDeclarationPO.getCreator(), ""))
                            .operateTime(SalaryDateUtil.getFormatLocalDateTime(taxDeclarationPO.getCreateTime()))
                            .description(taxDeclarationPO.getDescription())
                            .opts(taxDeclarationPO.getOpts())
                            .build();
                })
                .collect(Collectors.toList());
    }

    public static void buildDetailListDTO(Long taxDeclarationId,
                                          PageInfo<TaxDeclarationDetailListDTO> page,
                                          List<TaxDeclarationDetailPO> taxDeclarationDetails,
                                          List<DataCollectionEmployee> simpleEmployees) {
        if (CollectionUtils.isEmpty(taxDeclarationDetails)) {
            return;
        }
        int index = (page.getNextPage() - 1) * page.getSize();
        List<TaxDeclarationDetailListDTO> dtos = Lists.newArrayListWithExpectedSize(simpleEmployees.size());
        Map<Long, List<TaxDeclarationDetailPO>> taxDeclarationDetailMap = SalaryEntityUtil.group2Map(taxDeclarationDetails, TaxDeclarationDetailPO::getEmployeeId);
        for (DataCollectionEmployee simpleEmployee : simpleEmployees) {
            Map<String, String> valueMap = SalaryEntityUtil.convert2Map(taxDeclarationDetailMap.get(simpleEmployee.getEmployeeId()), TaxDeclarationDetailPO::getFieldCode, TaxDeclarationDetailPO::getFieldValue);
            TaxDeclarationDetailListDTO dto = new TaxDeclarationDetailListDTO();
            dto.setId(simpleEmployee.getEmployeeId());
            dto.setTaxDeclarationId(taxDeclarationId);
            dto.setSeq(++index);
            dto.setEmployeeId(simpleEmployee.getEmployeeId());
            dto.setEmployeeName(simpleEmployee.getUsername());
            dto.setIdCardType(SalaryI18nUtil.getI18nLabel(101696, "身份证"));
            dto.setIdCardNo("");
            dto.setTaxpayerIdNo("");
            dto.setResidentType(SalaryI18nUtil.getI18nLabel(101697, "居民"));
            dto.setIncomeType(SalaryI18nUtil.getI18nLabel(101698, "工资、薪金"));
            dto.setIncome(valueMap.getOrDefault("income", ""));
            dto.setFee(valueMap.getOrDefault("fee", ""));
            dto.setTaxFreeIncome(valueMap.getOrDefault("taxFreeIncome", ""));
            dto.setSubtraction(valueMap.getOrDefault("subtraction", ""));
            dto.setEndowmentInsurance(valueMap.getOrDefault("endowmentInsurance", ""));
            dto.setMedicalInsurance(valueMap.getOrDefault("medicalInsurance", ""));
            dto.setUnemploymentInsurance(valueMap.getOrDefault("unemploymentInsurance", ""));
            dto.setHousingProvidentFund(valueMap.getOrDefault("housingProvidentFund", ""));
            dto.setAnnuity(valueMap.getOrDefault("annuity", ""));
            dto.setCommercialHealthInsurance(valueMap.getOrDefault("commercialHealthInsurance", ""));
            dto.setTaxDeferredEndowmentInsurance(valueMap.getOrDefault("taxDeferredEndowmentInsurance", ""));
            dto.setOriginalValueOfProperty(valueMap.getOrDefault("originalValueOfProperty", ""));
            dto.setDeductedTax(valueMap.getOrDefault("deductedTax", ""));
            dto.setOther(valueMap.getOrDefault("other", ""));
            dto.setAddUpIncome(valueMap.getOrDefault("addUpIncome", ""));
            dto.setAddUpSubtraction(valueMap.getOrDefault("addUpSubtraction", ""));
            dto.setAddUpSpecialDeduction(valueMap.getOrDefault("addUpSpecialDeduction", ""));
            dto.setAddUpChildEducation(valueMap.getOrDefault("addUpChildEducation", ""));
            dto.setAddUpContinuingEducation(valueMap.getOrDefault("addUpContinuingEducation", ""));
            dto.setAddUpHousingLoanInterest(valueMap.getOrDefault("addUpHousingLoanInterest", ""));
            dto.setAddUpHousingRent(valueMap.getOrDefault("addUpHousingRent", ""));
            dto.setAddUpSupportElderly(valueMap.getOrDefault("addUpSupportElderly", ""));
            dto.setAddUpOther(valueMap.getOrDefault("addUpOtherDeduction", ""));
            dto.setLessTaxProportion(valueMap.getOrDefault("lessTaxProportion", ""));
            dto.setAllowedDonation(valueMap.getOrDefault("addUpAllowedDonation", ""));
            dto.setTaxableIncome(valueMap.getOrDefault("addUpTaxableIncome", ""));
            dto.setTaxRate(valueMap.getOrDefault("taxRate", ""));
            dto.setQuickDeductionFactor(valueMap.getOrDefault("quickDeductionFactor", ""));
            dto.setTaxPayable(valueMap.getOrDefault("addUpTaxPayable", ""));
            dto.setTaxSavings(valueMap.getOrDefault("addUpTaxDeduction", ""));
            dto.setTaxWithheld(valueMap.getOrDefault("taxWithheld", ""));
            dto.setRefundedOrSupplementedTax(valueMap.getOrDefault("refundedOrSupplementedTax", ""));
            dtos.add(dto);
        }
        page.setList(dtos);
    }

    public static Result handle(TaxDeclarationSaveParam saveParam,
                                Date taxCycle,
                                User user,
                                List<SalaryItemPO> salaryItems,
                                List<SalarySobPO> salarySobs,
                                List<SalaryAcctResultPO> salaryAcctResults) {
        Result result = new Result();
        if (CollectionUtils.isEmpty(salaryAcctResults)) {
            return result;
        }
        // 薪资项目聚合成map（为了根据code获取id）
        Map<String, Long> salaryItemMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getCode, SalaryItemPO::getId);
        // 薪资账套聚合成map（为了根据id获取incomeCategory）
        Map<Long, SalarySobPO> salarySobPOMap = SalaryEntityUtil.convert2Map(salarySobs, SalarySobPO::getId);
        // 薪资核算结果按照个税扣缴义务人id、所用薪资账套的incomeCategory聚合成map
        Map<Long, Map<Integer, List<SalaryAcctResultPO>>> taxAgentIdKeyAcctResultMap = salaryAcctResults.stream()
                .collect(Collectors.groupingBy(SalaryAcctResultPO::getTaxAgentId,
                        Collectors.groupingBy(salaryAcctResultPO -> salarySobPOMap.get(salaryAcctResultPO.getSalarySobId()).getIncomeCategory())));
        // 一个个税扣缴义务人，一种薪资类型生成一张个税申报表
        taxAgentIdKeyAcctResultMap.forEach((taxAgentId, incomeCategoryKeyAcctResultPOMap) -> {
            incomeCategoryKeyAcctResultPOMap.forEach((incomeCategory, salaryAcctResultPOS) -> {
                // 新增的个税申报表
                TaxDeclarationPO taxDeclaration = convert2PO(saveParam, user, taxCycle, taxAgentId, incomeCategory);
                result.getNeedInsertTaxDeclarations().add(taxDeclaration);
                if (Objects.equals(incomeCategory, IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) {
                    // 生成个税申报表
                    handleTaxDeclaration4Wage(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap);
                    // 生成往期累计情况
                    handleAddUpSituation(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap);
                }
                if (Objects.equals(incomeCategory, IncomeCategoryEnum.REMUNERATION_FOR_LABOR.getValue())) {
                    // 生成个税申报表
                    handleTaxDeclaration4Labor(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap);
                }
                if (Objects.equals(incomeCategory, IncomeCategoryEnum.ONETIME_ANNUAL_BONUS.getValue())) {
                    // 生成个税申报表
                    handleTaxDeclaration4Annual(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap);
                }
            });
        });
        return result;
    }

    /**
     * 生成个税申报表明细（正常工资薪金所得）
     *
     * @param result
     * @param taxDeclaration
     * @param salaryAcctResults
     * @param salaryItemMap
     */
    private static void handleTaxDeclaration4Wage(Result result,
                                                  TaxDeclarationPO taxDeclaration,
                                                  List<SalaryAcctResultPO> salaryAcctResults,
                                                  Map<String, Long> salaryItemMap) {
        if (CollectionUtils.isEmpty(salaryAcctResults)) {
            return;
        }
        // 核算结果按照人员id分类
        Map<String, List<SalaryAcctResultPO>> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults,
                salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId());
        salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> {
            String[] keyArray = StringUtils.split(key, "_");
            // 员工类型
            Integer employeeType = Integer.parseInt(keyArray[0]);
            // 员工id
            Long employeeId = Long.parseLong(keyArray[1]);
            Map<String, String> valueMap = Maps.newHashMapWithExpectedSize(17);
            Map<Long, List<SalaryAcctResultPO>> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId);
            // 本期收入
            BigDecimal income = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.INCOME, 0L)),
                    salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue()));
            valueMap.put(TaxDeclarationDataIndexConstant.INCOME, income.toPlainString());
            // 本期免税收入
            BigDecimal taxFreeIncome = findValue(TaxDeclarationDataIndexConstant.TAX_FREE_INCOME, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.TAX_FREE_INCOME, taxFreeIncome.toPlainString());
            // 基本养老保险
            BigDecimal endowmentInsurance = findValue(TaxDeclarationDataIndexConstant.ENDOWMENT_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ENDOWMENT_INSURANCE, endowmentInsurance.toPlainString());
            // 基本医疗保险
            BigDecimal medicalInsurance = findValue(TaxDeclarationDataIndexConstant.MEDICAL_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.MEDICAL_INSURANCE, medicalInsurance.toPlainString());
            // 失业保险费
            BigDecimal unemploymentInsurance = findValue(TaxDeclarationDataIndexConstant.UNEMPLOYMENT_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.UNEMPLOYMENT_INSURANCE, unemploymentInsurance.toPlainString());
            // 住房公积金
            BigDecimal housingProvidentFund = findValue(TaxDeclarationDataIndexConstant.HOUSING_PROVIDENT_FUND, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.HOUSING_PROVIDENT_FUND, housingProvidentFund.toPlainString());
            // 累计子女教育
            BigDecimal addUpChildEducation = findValue(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, addUpChildEducation.toPlainString());
            // 累计继续教育
            BigDecimal addUpContinuingEducation = findValue(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, addUpContinuingEducation.toPlainString());
            // 累计住房贷款利息
            BigDecimal addUpHousingLoanInterest = findValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, addUpHousingLoanInterest.toPlainString());
            // 累计住房租金
            BigDecimal addUpHousingRent = findValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, addUpHousingRent.toPlainString());
            // 累计赡养老人
            BigDecimal addUpSupportElderly = findValue(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, addUpSupportElderly.toPlainString());
            // 累计大病医疗
            BigDecimal addUpIllnessMedical = findValue(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, addUpIllnessMedical.toPlainString());
            // 累计婴幼儿照护
            BigDecimal addUpInfantCare = findValue(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, addUpInfantCare.toPlainString());
            // 累计个人养老金
            BigDecimal addUpPrivatePension = findValue(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, addUpPrivatePension.toPlainString());
            // 企业(职业)年金
            BigDecimal annuity = findValue(TaxDeclarationDataIndexConstant.ANNUITY, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUITY, annuity.toPlainString());
            // 商业健康保险
            BigDecimal commercialHealthInsurance = findValue(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, commercialHealthInsurance.toPlainString());
            // 税延养老保险
            BigDecimal taxDeferredEndowmentInsurance = findValue(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, taxDeferredEndowmentInsurance.toPlainString());
            // 其他
            BigDecimal other = findValue(TaxDeclarationDataIndexConstant.OTHER, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.OTHER, other.toPlainString());
            // 准予扣除的捐赠额
            BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, allowedDonation.toPlainString());
            // 减免税额
            BigDecimal taxDeduction = findValue(TaxDeclarationDataIndexConstant.TAX_DEDUCTION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEDUCTION, taxDeduction.toPlainString());
            // 生成个税申报表详情
            result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap));
        });
    }

    /**
     * 生成个税申报表明细（劳务报酬所得）
     *
     * @param result
     * @param taxDeclaration
     * @param salaryAcctResults
     * @param salaryItemMap
     */
    private static void handleTaxDeclaration4Labor(Result result,
                                                   TaxDeclarationPO taxDeclaration,
                                                   List<SalaryAcctResultPO> salaryAcctResults,
                                                   Map<String, Long> salaryItemMap) {
        if (CollectionUtils.isEmpty(salaryAcctResults)) {
            return;
        }
        // 核算结果按照人员id分类
        Map<String, List<SalaryAcctResultPO>> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId());
        salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> {
            String[] keyArray = StringUtils.split(key, "_");
            Integer employeeType = Integer.parseInt(keyArray[0]);
            Long employeeId = Long.parseLong(keyArray[1]);
            Map<String, String> valueMap = Maps.newHashMapWithExpectedSize(7);
            Map<Long, List<SalaryAcctResultPO>> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId);
            // 所得项目
            String incomeItems = resultMap.getOrDefault(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.INCOME_ITEMS, 0L), Collections.emptyList()).stream()
                    .map(SalaryAcctResultPO::getResultValue)
                    .findAny()
                    .orElse(StringUtils.EMPTY);
            valueMap.put(TaxDeclarationDataIndexConstant.INCOME_ITEMS, incomeItems);
            // 收入
            BigDecimal laborIncome = findValue(TaxDeclarationDataIndexConstant.LABOR_INCOME, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.LABOR_INCOME, laborIncome.toPlainString());
            // 免税收入
            BigDecimal laborTaxFreeIncome = findValue(TaxDeclarationDataIndexConstant.LABOR_TAX_FREE_INCOME, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.LABOR_TAX_FREE_INCOME, laborTaxFreeIncome.toPlainString());
            // 商业健康保险
            BigDecimal commercialHealthInsurance = findValue(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, commercialHealthInsurance.toPlainString());
            // 税延养老保险
            BigDecimal taxDeferredEndowmentInsurance = findValue(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, taxDeferredEndowmentInsurance.toPlainString());
            // 其他
            BigDecimal other = findValue(TaxDeclarationDataIndexConstant.OTHER, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.OTHER, other.toPlainString());
            // 准予扣除的捐赠额
            BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, allowedDonation.toPlainString());
            // 生成个税申报表详情
            result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap));
        });
    }

    /**
     * 生成个税申报表明细（年终奖）
     *
     * @param result
     * @param taxDeclaration
     * @param salaryAcctResults
     * @param salaryItemMap
     */
    private static void handleTaxDeclaration4Annual(Result result,
                                                   TaxDeclarationPO taxDeclaration,
                                                   List<SalaryAcctResultPO> salaryAcctResults,
                                                   Map<String, Long> salaryItemMap) {
        if (CollectionUtils.isEmpty(salaryAcctResults)) {
            return;
        }
        // 核算结果按照人员id分类
        Map<String, List<SalaryAcctResultPO>> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId());
        salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> {
            String[] keyArray = StringUtils.split(key, "_");
            Integer employeeType = Integer.parseInt(keyArray[0]);
            Long employeeId = Long.parseLong(keyArray[1]);
            Map<String, String> valueMap = Maps.newHashMapWithExpectedSize(7);
            Map<Long, List<SalaryAcctResultPO>> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId);
            // 全年一次性奖金额
            BigDecimal laborIncome = findValue(TaxDeclarationDataIndexConstant.ANNUAL_INCOME, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_INCOME, laborIncome.toPlainString());
            // 免税收入
            BigDecimal laborTaxFreeIncome = findValue(TaxDeclarationDataIndexConstant.ANNUAL_TAX_FREE_INCOME, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_TAX_FREE_INCOME, laborTaxFreeIncome.toPlainString());
            // 其他
            BigDecimal other = findValue(TaxDeclarationDataIndexConstant.ANNUAL_OTHER, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_OTHER, other.toPlainString());
            // 准予扣除的捐赠额
            BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ANNUAL_DONATE_TAX, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_DONATE_TAX, allowedDonation.toPlainString());
            // 减免税额
            BigDecimal annualTaxSavings = findValue(TaxDeclarationDataIndexConstant.ANNUAL_TAX_SAVINGS, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_TAX_SAVINGS, annualTaxSavings.toPlainString());
            // 备注
            String annualRemark = findStringValue(TaxDeclarationDataIndexConstant.ANNUAL_REMARK, resultMap, salaryItemMap);
            valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_REMARK, annualRemark);
            // 生成个税申报表详情
            result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap));
        });
    }

    /**
     * 往期累计情况
     *
     * @param result
     * @param taxDeclaration
     * @param salaryAcctResults
     * @param salaryItemMap
     */
    private static void handleAddUpSituation(Result result,
                                             TaxDeclarationPO taxDeclaration,
                                             List<SalaryAcctResultPO> salaryAcctResults,
                                             Map<String, Long> salaryItemMap) {
        if (CollectionUtils.isEmpty(salaryAcctResults)) {
            return;
        }
        // 核算结果按照人员id分类
        Map<String, List<SalaryAcctResultPO>> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId());
        salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> {
            String[] keyArray = key.split("_");
            Integer employeeType = Integer.parseInt(keyArray[0]);
            Long employeeId = Long.parseLong(keyArray[1]);
            Map<Long, List<SalaryAcctResultPO>> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId);
            // 累计收入额
            BigDecimal addUpIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_INCOME, resultMap, salaryItemMap);
            // 累计免税收入
            BigDecimal addUpTaxFreeIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_FREE_INCOME, resultMap, salaryItemMap);
            // 累计减除费用
            BigDecimal addUpSubtraction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SUBTRACTION, resultMap, salaryItemMap);
            // 累计社保个人合计
            BigDecimal addUpSocialSecurityTotal = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SOCIAL_SECURITY_TOTAL, resultMap, salaryItemMap);
            // 累计公积金个人合计
            BigDecimal addUpAccumulationFundTotal = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ACCUMULATION_FUND_TOTAL, resultMap, salaryItemMap);
            // 累计子女教育
            BigDecimal addUpChildEducation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, resultMap, salaryItemMap);
            // 累计继续教育
            BigDecimal addUpContinuingEducation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, resultMap, salaryItemMap);
            // 累计住房贷款利息
            BigDecimal addUpHousingLoanInterest = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, resultMap, salaryItemMap);
            // 累计住房租金
            BigDecimal addUpHousingRent = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, resultMap, salaryItemMap);
            // 累计赡养老人
            BigDecimal addUpSupportElderly = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, resultMap, salaryItemMap);
            // 累计大病医疗
            BigDecimal addUpIllnessMedical = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, resultMap, salaryItemMap);
            // 累计婴幼儿照护
            BigDecimal addUpInfantCare = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, resultMap, salaryItemMap);
            // 累计个人养老金
            BigDecimal addUpPrivatePension = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, resultMap, salaryItemMap);
            // 累计企业（职业）年金及其他福利
            BigDecimal addUpEnterpriseAndOther = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ENTERPRISE_AND_OTHER, resultMap, salaryItemMap);
            // 累计其他免税扣除
            BigDecimal addUpOtherDeduction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_OTHER_DEDUCTION, resultMap, salaryItemMap);
            // 累计准予扣除的捐赠额
            BigDecimal addUpAllowedDonation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ALLOWED_DONATION, resultMap, salaryItemMap);
            // 累计应纳税所得额
            BigDecimal addUpTaxableIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAXABLE_INCOME, resultMap, salaryItemMap);
            // 累计应纳税额
            BigDecimal addUpTaxPayable = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_PAYABLE, resultMap, salaryItemMap);
            //累计减免税额
            BigDecimal addUpTaxDeduction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_DEDUCTION, resultMap, salaryItemMap);
            // 累计已预扣预缴税额
            List<SalaryAcctResultPO> resultPOS = resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.ADD_UP_ADVANCE_TAX, 0L));
            BigDecimal addUpAdvanceTax = resultPOS == null ? BigDecimal.ZERO : resultPOS.stream()
                    .map(salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue()))
                    .min(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO);
            // 本月（次）应补（退）税额
            BigDecimal refundedOrSupplementedTax = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.REFUNDED_OR_SUPPLEMENTED_TAX, 0L)),
                    salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue()));
            // 生成往期累计情况
            AddUpSituation accumulatedSituation = AddUpSituation.builder()
                    .employeeId(employeeId)
//                    .employeeType(employeeType)
                    .taxAgentId(taxDeclaration.getTaxAgentId())
                    .taxYearMonth(taxDeclaration.getTaxCycle())
                    .year(SalaryDateUtil.date2Year(taxDeclaration.getTaxCycle()))
                    .addUpIncome(addUpIncome.toPlainString())
                    .addUpSocialSecurityTotal(addUpSocialSecurityTotal.toPlainString())
                    .addUpAccumulationFundTotal(addUpAccumulationFundTotal.toPlainString())
                    .addUpEnterpriseAndOther(addUpEnterpriseAndOther.toPlainString())
                    .addUpSubtraction(addUpSubtraction.toPlainString())
                    .addUpChildEducation(addUpChildEducation.toPlainString())
                    .addUpContinuingEducation(addUpContinuingEducation.toPlainString())
                    .addUpHousingLoanInterest(addUpHousingLoanInterest.toPlainString())
                    .addUpHousingRent(addUpHousingRent.toPlainString())
                    .addUpSupportElderly(addUpSupportElderly.toPlainString())
                    .addUpIllnessMedical(addUpIllnessMedical.toPlainString())
                    .addUpInfantCare(addUpInfantCare.toPlainString())
                    .addUpPrivatePension(addUpPrivatePension.toPlainString())
                    .addUpOtherDeduction(addUpOtherDeduction.toPlainString())
                    .addUpTaxExemptIncome(addUpTaxFreeIncome.toPlainString())
                    .addUpAllowedDonation(addUpAllowedDonation.toPlainString())
                    .addUpAdvanceTax(addUpAdvanceTax.add(refundedOrSupplementedTax).toPlainString())
                    .addUpTaxSavings(addUpTaxDeduction.toPlainString())
                    .creator(taxDeclaration.getCreator())
                    .createTime(taxDeclaration.getCreateTime())
                    .updateTime(taxDeclaration.getUpdateTime())
                    .tenantKey(taxDeclaration.getTenantKey())
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build();
            encryptUtil.encrypt(accumulatedSituation, AddUpSituation.class);
            result.getNeedInsertAddUpSituations().add(accumulatedSituation);
        });
    }


//    private static void handleTaxDeclarationDetail(Result result,
//                                                   TaxDeclarationPO taxDeclaration,
//                                                   List<SalaryAcctResultPO> salaryAcctResults,
//                                                   Map<String, Long> salaryItemMap) {
//        if (CollectionUtils.isEmpty(salaryAcctResults)) {
//            return;
//        }
//        // 核算结果按照人员id分类
//        Map<Long, List<SalaryAcctResultPO>> acctResultMap = SalaryEntityUtil.group2Map(salaryAcctResults, SalaryAcctResultPO::getEmployeeId);
//        acctResultMap.forEach((k, v) -> {
//            Long employeeId = k;
//            Map<String, BigDecimal> valueMap = new HashMap<>();
//            Map<Long, List<SalaryAcctResultPO>> resultMap = SalaryEntityUtil.group2Map(v, SalaryAcctResultPO::getSalaryItemId);
//            // 收入
//            BigDecimal income = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault("income", 0L)), e -> SalaryEntityUtil.empty2Zero(e.getResultValue()));
//            valueMap.put("income", income);
//            // 费用
//            BigDecimal fee = BigDecimal.ZERO;
//            valueMap.put("fee", fee);
//            // 免税收入
//            BigDecimal taxFreeIncome = BigDecimal.ZERO;
//            valueMap.put("taxFreeIncome", taxFreeIncome);
//            // 减除费用
//            BigDecimal subtraction = findValue("subtraction", resultMap, salaryItemMap);
//            valueMap.put("subtraction", subtraction);
//            // 基本养老保险
//            BigDecimal endowmentInsurance = findValue("endowmentInsurance", resultMap, salaryItemMap);
//            valueMap.put("endowmentInsurance", endowmentInsurance);
//            // 基本医疗保险
//            BigDecimal medicalInsurance = findValue("medicalInsurance", resultMap, salaryItemMap);
//            valueMap.put("medicalInsurance", medicalInsurance);
//            // 失业保险
//            BigDecimal unemploymentInsurance = findValue("unemploymentInsurance", resultMap, salaryItemMap);
//            valueMap.put("unemploymentInsurance", unemploymentInsurance);
//            // 住房公积金
//            BigDecimal housingProvidentFund = findValue("housingProvidentFund", resultMap, salaryItemMap);
//            valueMap.put("housingProvidentFund", housingProvidentFund);
//            // 年金
//            BigDecimal annuity = findValue("annuity", resultMap, salaryItemMap);
//            valueMap.put("annuity", annuity);
//            // 商业健康保险
//            BigDecimal commercialHealthInsurance = findValue("commercialHealthInsurance", resultMap, salaryItemMap);
//            valueMap.put("commercialHealthInsurance", commercialHealthInsurance);
//            // 税延养老保险
//            BigDecimal taxDeferredEndowmentInsurance = findValue("taxDeferredEndowmentInsurance", resultMap, salaryItemMap);
//            valueMap.put("taxDeferredEndowmentInsurance", taxDeferredEndowmentInsurance);
//            // 财产原值
//            BigDecimal originalValueOfProperty = findValue("originalValueOfProperty", resultMap, salaryItemMap);
//            valueMap.put("originalValueOfProperty", originalValueOfProperty);
//            // 允许扣除的税费
//            BigDecimal deductedTax = findValue("deductedTax", resultMap, salaryItemMap);
//            valueMap.put("deductedTax", deductedTax);
//            // 其他
//            BigDecimal other = findValue("other", resultMap, salaryItemMap);
//            valueMap.put("other", other);
//            // 累计收入
//            BigDecimal addUpIncome = findAddUpValue("addUpIncome", resultMap, salaryItemMap);
//            valueMap.put("addUpIncome", addUpIncome);
//            // 累计免税收入
//            BigDecimal addUpTaxFreeIncome = findAddUpValue("addUpTaxFreeIncome", resultMap, salaryItemMap);
//            valueMap.put("addUpTaxFreeIncome", addUpTaxFreeIncome);
//            // 累计减除费用
//            BigDecimal addUpSubtraction = findAddUpValue("addUpSubtraction", resultMap, salaryItemMap);
//            valueMap.put("addUpSubtraction", addUpSubtraction);
//            // 累计专项扣除
//            BigDecimal addUpSpecialDeduction = findAddUpValue("addUpSpecialDeduction", resultMap, salaryItemMap);
//            valueMap.put("addUpSpecialDeduction", addUpSpecialDeduction);
//            // 累计子女教育
//            BigDecimal addUpChildEducation = findAddUpValue("addUpChildEducation", resultMap, salaryItemMap);
//            valueMap.put("addUpChildEducation", addUpChildEducation);
//            // 累计继续教育
//            BigDecimal addUpContinuingEducation = findAddUpValue("addUpContinuingEducation", resultMap, salaryItemMap);
//            valueMap.put("addUpContinuingEducation", addUpContinuingEducation);
//            // 累计住房贷款利息
//            BigDecimal addUpHousingLoanInterest = findAddUpValue("addUpHousingLoanInterest", resultMap, salaryItemMap);
//            valueMap.put("addUpHousingLoanInterest", addUpHousingLoanInterest);
//            // 累计住房租金
//            BigDecimal addUpHousingRent = findAddUpValue("addUpHousingRent", resultMap, salaryItemMap);
//            valueMap.put("addUpHousingRent", addUpHousingRent);
//            // 累计赡养老人
//            BigDecimal addUpSupportElderly = findAddUpValue("addUpSupportElderly", resultMap, salaryItemMap);
//            valueMap.put("addUpSupportElderly", addUpSupportElderly);
//            // 累计大病医疗
//            BigDecimal addUpIllnessMedical = findAddUpValue("addUpIllnessMedical", resultMap, salaryItemMap);
//            valueMap.put("addUpIllnessMedical", addUpIllnessMedical);
//            // 累计婴幼儿照护
//            BigDecimal addUpInfantCare = findAddUpValue("addUpInfantCare", resultMap, salaryItemMap);
//            valueMap.put("addUpInfantCare", addUpInfantCare);
//            // 累计其他扣除
//            BigDecimal addUpOtherDeduction = findAddUpValue("addUpOtherDeduction", resultMap, salaryItemMap);
//            valueMap.put("addUpOtherDeduction", addUpOtherDeduction);
//            // 减按计税比例
//            BigDecimal lessTaxProportion = BigDecimal.ONE;
//            valueMap.put("lessTaxProportion", lessTaxProportion);
//            // 准允扣除的捐赠额
//            BigDecimal addUpAllowedDonation = findAddUpValue("addUpAllowedDonation", resultMap, salaryItemMap);
//            valueMap.put("addUpAllowedDonation", addUpAllowedDonation);
//            // 应纳税所得额
//            BigDecimal addUpTaxableIncome = findAddUpValue("addUpTaxableIncome", resultMap, salaryItemMap);
//            valueMap.put("addUpTaxableIncome", addUpTaxableIncome);
//            // 税率
//            BigDecimal taxRate = findAddUpValue("taxRate", resultMap, salaryItemMap);
//            valueMap.put("taxRate", taxRate);
//            // 速算扣除数
//            BigDecimal quickDeductionFactor = findAddUpValue("quickDeductionFactor", resultMap, salaryItemMap);
//            valueMap.put("quickDeductionFactor", quickDeductionFactor);
//            // 应纳税额
//            BigDecimal addUpTaxPayable = findAddUpValue("addUpTaxPayable", resultMap, salaryItemMap);
//            valueMap.put("addUpTaxPayable", addUpTaxPayable);
//            // 减免税额
//            BigDecimal addUpTaxDeduction = BigDecimal.ZERO;
//            valueMap.put("addUpTaxDeduction", addUpTaxDeduction);
//            // 减免税额
//            BigDecimal taxDeduction = findValue("taxDeduction", resultMap, salaryItemMap);
//            valueMap.put("taxDeduction", taxDeduction);
//            // 应补缴税额
//            BigDecimal refundedOrSupplementedTax = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault("refundedOrSupplementedTax", 0L)),
//                    e -> SalaryEntityUtil.empty2Zero(e.getResultValue()));
//            valueMap.put("refundedOrSupplementedTax", refundedOrSupplementedTax);
//            // 已扣缴税额
//            BigDecimal taxWithheld = addUpTaxPayable.subtract(refundedOrSupplementedTax);
//            valueMap.put("taxWithheld", taxWithheld);
//
//            valueMap.forEach((key, value) -> {
//                TaxDeclarationDetailPO detailPO = TaxDeclarationDetailPO.builder()
//                        .taxDeclarationId(taxDeclaration.getId())
//                        .employeeId(k)
//                        .fieldCode(key)
//                        .fieldValue(value.toPlainString())
//                        .creator(taxDeclaration.getCreator())
//                        .createTime(taxDeclaration.getCreateTime())
//                        .updateTime(taxDeclaration.getUpdateTime())
//                        .deleteType(0)
//                        .tenantKey(taxDeclaration.getTenantKey())
//                        .build();
//                result.getNeedInsertTaxDeclarationDetails().add(detailPO);
//            });
//            // 累计社保个人合计
//            BigDecimal addUpSocialSecurityTotal = findAddUpValue("addUpSocialSecurityTotal", resultMap, salaryItemMap);
//            // 累计公积金个人合计
//            BigDecimal addUpAccumulationFundTotal = findAddUpValue("addUpAccumulationFundTotal", resultMap, salaryItemMap);
//            // 累计年金及其他福利合计
//            BigDecimal addUpEnterpriseAndOther = findAddUpValue("addUpEnterpriseAndOther", resultMap, salaryItemMap);
//
//            // 更新累计情况
//            AddUpSituation accumulatedSituation = AddUpSituation.builder()
//                    .employeeId(employeeId)
//                    .taxAgentId(taxDeclaration.getTaxAgentId())
//                    .taxYearMonth(taxDeclaration.getTaxCycle())
//                    .year(SalaryDateUtil.date2Year(taxDeclaration.getTaxCycle()))
//                    .addUpIncome(addUpIncome.toPlainString())
//                    .addUpSocialSecurityTotal(addUpSocialSecurityTotal.toPlainString())
//                    .addUpAccumulationFundTotal(addUpAccumulationFundTotal.toPlainString())
//                    .addUpEnterpriseAndOther(addUpEnterpriseAndOther.toPlainString())
//                    .addUpSubtraction(addUpSubtraction.toPlainString())
//                    .addUpChildEducation(addUpChildEducation.toPlainString())
//                    .addUpContinuingEducation(addUpContinuingEducation.toPlainString())
//                    .addUpHousingLoanInterest(addUpHousingLoanInterest.toPlainString())
//                    .addUpHousingRent(addUpHousingRent.toPlainString())
//                    .addUpSupportElderly(addUpSupportElderly.toPlainString())
//                    .addUpIllnessMedical(addUpIllnessMedical.toPlainString())
//                    .addUpInfantCare(addUpInfantCare.toPlainString())
//                    .addUpOtherDeduction(addUpOtherDeduction.toPlainString())
//                    .addUpTaxExemptIncome(addUpTaxFreeIncome.toPlainString())
//                    .addUpAllowedDonation(addUpAllowedDonation.toPlainString())
//                    .addUpAdvanceTax(addUpTaxPayable.toPlainString())
////                    .addUpTaxSavings(taxDeduction.toPlainString())
//                    .creator(taxDeclaration.getCreator())
//                    .createTime(taxDeclaration.getCreateTime())
//                    .updateTime(taxDeclaration.getUpdateTime())
//                    .tenantKey(taxDeclaration.getTenantKey())
//                    .deleteType(NumberUtils.INTEGER_ZERO)
//                    .build();
//            result.getNeedInsertAccumulatedSituations().add(accumulatedSituation);
//        });
//    }

    private static TaxDeclarationPO convert2PO(TaxDeclarationSaveParam saveParam, User user, Date taxCycle, Long taxAgentId, Integer incomeCategory) {
        LocalDateTime now = LocalDateTime.now();
        if (saveParam.getDescription() == null) {
            saveParam.setDescription("");
        }
        return TaxDeclarationPO.builder()
                .id(IdGenerator.generate())
                .incomeCategory(incomeCategory)
                .taxAgentId(taxAgentId)
                .salaryMonth(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)))
                .taxCycle(taxCycle)
                .description(saveParam.getDescription())
                .creator((long) user.getUID())
                .createTime(SalaryDateUtil.localDateTimeToDate(now))
                .updateTime(SalaryDateUtil.localDateTimeToDate(now))
                .deleteType(0)
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                .build();
    }

    /**
     * 根据参数生成个税申报表详情po
     *
     * @param taxDeclaration
     * @param employeeId
     * @param valueMap
     * @return
     */
    private static List<TaxDeclarationDetailPO> convert2DetailPO(TaxDeclarationPO taxDeclaration, Integer employeeType, Long employeeId, Map<String, String> valueMap) {
        if (MapUtils.isEmpty(valueMap)) {
            return Collections.emptyList();
        }
        List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = Lists.newArrayListWithExpectedSize(valueMap.size());
        valueMap.forEach((fieldCode, fieldValue) -> {
            TaxDeclarationDetailPO taxDeclarationDetailPO = TaxDeclarationDetailPO.builder()
                    .id(IdGenerator.generate())
                    .taxDeclarationId(taxDeclaration.getId())
                    .employeeType(employeeType)
                    .employeeId(employeeId)
                    .fieldCode(fieldCode)
                    .fieldValue(fieldValue)
                    .creator(taxDeclaration.getCreator())
                    .createTime(taxDeclaration.getCreateTime())
                    .updateTime(taxDeclaration.getUpdateTime())
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(taxDeclaration.getTenantKey())
                    .build();
            taxDeclarationDetailPOS.add(taxDeclarationDetailPO);
        });
        return taxDeclarationDetailPOS;
    }

    private static BigDecimal findValue(String fieldCode, Map<Long, List<SalaryAcctResultPO>> resultMap, Map<String, Long> salaryItemMap) {
        return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream()
                .map(e -> SalaryEntityUtil.empty2Zero(e.getResultValue()))
                .filter(e -> e.compareTo(BigDecimal.ZERO) > 0)
                .findAny()
                .orElse(BigDecimal.ZERO);
    }

    private static BigDecimal findAddUpValue(String fieldCode, Map<Long, List<SalaryAcctResultPO>> resultMap, Map<String, Long> salaryItemMap) {
        return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream()
                .map(e -> SalaryEntityUtil.empty2Zero(e.getResultValue()))
                .max(Comparator.comparingDouble(BigDecimal::doubleValue))
                .orElse(BigDecimal.ZERO);
    }

    private static String findStringValue(String fieldCode, Map<Long, List<SalaryAcctResultPO>> resultMap, Map<String, Long> salaryItemMap) {
        return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream()
                .map(SalaryAcctResultPO::getResultValue)
                .findFirst().orElse("");
    }

    @Data
    public static class Result {

        private Collection<TaxDeclarationPO> needInsertTaxDeclarations;

        private Collection<TaxDeclarationDetailPO> needInsertTaxDeclarationDetails;

        private Collection<AddUpSituation> needInsertAddUpSituations;

        public Result() {
            this.needInsertTaxDeclarations = Lists.newArrayList();
            this.needInsertTaxDeclarationDetails = Lists.newArrayList();
            this.needInsertAddUpSituations = Lists.newArrayList();
        }
    }
}
